#include "UploadWorker.h"
#include <QIODevice>
#include <QNetworkRequest>
#define DEBUG
#include <debug.h>
#define ALLOWED_DEBUG_LEVEL DBG_5

/*
 * FIXME: CANCEL AUTHORIZATION
 * PROGRESS EMITTING
 */





UploadWorker::UploadWorker(QObject *parent, QNetworkAccessManager *netManager)
	: QObject(parent),
	netMgr(netManager),
	requestFailed(false),
	canceled(false)
{
	links = QList<UploadResult>();
}

bool UploadWorker::append(const ImageToUpload &image) {
	try {
		QIODevice *dev = image.Image;
		if (!reOpenDevice(dev))
			throw fileException("can't reopen device: "+dev->errorString());
		if ( !appendImageToPost(image) )
			throw fileException("can't append image to post");
		else
			images.append(image);
	}
	catch (fileException &e) {
		emit fileError(image.index, e.errorStr()); //FIXME
		warn << e.errorStr();
		return false;
	}
	return true;
}

void UploadWorker::run() {
	this->collectPostData();
	data.finalize();
	QNetworkRequest req(hostingUrl());
	setHeaders(req);
	reply = netMgr->post(req, data);
	connect(reply, SIGNAL(finished()), this, SLOT(requestFinished()));
	connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
		this, SLOT(requestError(QNetworkReply::NetworkError)));
	connect(reply, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(updateProgress(qint64,qint64)));
	foreach ( const ImageToUpload &img, images )
		emit startFile(img.index);
}

void UploadWorker::requestFinished() {
	if ( requestFailed || canceled ) {
		emit finished();
		return;
	}
	QList<UploadResult> result = parseResponse();
	foreach (UploadResult res, result) {
		qDebug() << "file res. success:" << res.success;
		if ( res.success )
			emit fileUploaded(res.index, res);
		else
			emit fileError(res.index, res.errorString);
	}
	this->links = result;
	emit finished();
}

void UploadWorker::requestError(QNetworkReply::NetworkError e) {
	err << "upload error:" << e;
	if ( canceled || e == QNetworkReply::OperationCanceledError ) {
		return;
	}
	this->requestFailed = true;
	const QMetaObject* mo = reply->metaObject();
	QString error(mo->enumerator(mo->indexOfEnumerator("NetworkError")).valueToKey(e));
	foreach (const ImageToUpload &image, images)
		emit fileError(image.index, error);
}

void UploadWorker::abort() {
	canceled = true;
	QList<UploadResult> resuslts;
	foreach ( ImageToUpload img, images ) {
		UploadResult res;
		qDebug() << "cancelling image " << img.ImageName << img.index;
		res.index = img.index;
		res.ImageName = img.ImageName;
		res.canceled = true;
		res.success = false;
		resuslts.append(res);
		emit fileUploaded(res.index, res);
	}
	this->links = resuslts;
	if ( !reply->isFinished() )
		reply->abort();
}

const QList<UploadResult>& UploadWorker::allLinks() const {
	return this->links;
}

void UploadWorker::updateProgress(qint64 value, qint64 max) {
	foreach (const ImageToUpload &img, images) {
		int nval = value * 100 / max;
		emit updateStatus(nval, 100, img.index);
	}
}

bool reOpenDevice(QIODevice *buffer, QIODevice::OpenMode Mode )
{
	if ( buffer->isOpen() && buffer->openMode() != Mode )
		buffer->close();
	if (! buffer->isOpen() ) {
		if (!buffer->open(Mode)) {
			qWarning() << "HTTP post: can't open given file"
			<< "(" + buffer->errorString() + ")";
			return false;
		}
	} else {
		if ( !buffer->reset() ) {
			qWarning() << "file is open, but I can't seek to beginning:" << buffer->errorString();
			return false;
		}
	}
	return true;
}





